<template>
  <div class="ssh-terminal">
    <div class="terminal-header">
      <div class="header-left">
        <h3>SSH终端 - {{ hostInfo.hostname }} ({{ hostInfo.ip_address }})</h3>
        <el-tag
          :type="getStatusType(connectionStatus)"
          size="small"
          style="margin-left: 10px"
        >
          {{ getStatusText(connectionStatus) }}
        </el-tag>
      </div>
      <div class="header-right">
        <el-button @click="reconnect" size="small" :disabled="connectionStatus === 'connecting'">
          重连
        </el-button>
        <el-button @click="closeTerminal" size="small">关闭</el-button>
      </div>
    </div>

    <div class="terminal-container">
      <div ref="terminalElement" class="terminal-element"></div>
    </div>

    <!-- 连接状态提示 -->
    <div v-if="connectionStatus === 'connecting'" class="connection-overlay">
      <div class="connection-message">
        <el-icon class="is-loading"><Loading /></el-icon>
        <span>正在连接到 {{ hostInfo.hostname }}...</span>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { Loading } from '@element-plus/icons-vue'
import { Terminal } from '@xterm/xterm'
import { FitAddon } from '@xterm/addon-fit'
import { WebLinksAddon } from '@xterm/addon-web-links'
import '@xterm/xterm/css/xterm.css'
import { cmdbAPI } from '../../api/cmdb'

const route = useRoute()
const router = useRouter()

const hostInfo = ref({})
const terminalElement = ref()
const connectionStatus = ref('disconnected') // disconnected, connecting, connected, failed

let terminal = null
let fitAddon = null
let websocket = null
let heartbeatInterval = null

const loadHostInfo = async () => {
  try {
    const hostId = route.params.hostId
    console.log('正在加载主机信息, hostId:', hostId)
    const response = await cmdbAPI.getHost(hostId)
    hostInfo.value = response
    console.log('主机信息加载成功:', response)
  } catch (error) {
    console.error('加载主机信息失败:', error)
    ElMessage.error('加载主机信息失败')
  }
}

const initTerminal = () => {
  // 创建终端实例
  terminal = new Terminal({
    cursorBlink: true,
    cursorStyle: 'block',
    fontSize: 14,
    fontFamily: 'Monaco, Menlo, "Ubuntu Mono", monospace',
    theme: {
      background: '#1e1e1e',
      foreground: '#ffffff',
      cursor: '#ffffff',
      selection: '#3e3e3e',
      black: '#000000',
      red: '#cd3131',
      green: '#0dbc79',
      yellow: '#e5e510',
      blue: '#2472c8',
      magenta: '#bc3fbc',
      cyan: '#11a8cd',
      white: '#e5e5e5',
      brightBlack: '#666666',
      brightRed: '#f14c4c',
      brightGreen: '#23d18b',
      brightYellow: '#f5f543',
      brightBlue: '#3b8eea',
      brightMagenta: '#d670d6',
      brightCyan: '#29b8db',
      brightWhite: '#e5e5e5'
    },
    allowTransparency: true,
    convertEol: true,
    scrollback: 1000
  })

  // 添加插件
  fitAddon = new FitAddon()
  terminal.loadAddon(fitAddon)
  terminal.loadAddon(new WebLinksAddon())

  // 打开终端
  terminal.open(terminalElement.value)

  // 适应容器大小
  fitAddon.fit()

  // 监听数据输入
  terminal.onData(data => {
    if (websocket && websocket.readyState === WebSocket.OPEN) {
      websocket.send(JSON.stringify({
        type: 'command',
        data: data
      }))
    }
  })

  // 监听窗口大小变化
  window.addEventListener('resize', handleResize)

  // 监听终端大小变化
  terminal.onResize(({ cols, rows }) => {
    if (websocket && websocket.readyState === WebSocket.OPEN) {
      websocket.send(JSON.stringify({
        type: 'resize',
        cols: cols,
        rows: rows
      }))
    }
  })
}

const connectWebSocket = () => {
  if (!hostInfo.value.id) {
    ElMessage.error('主机信息未加载')
    return
  }

  connectionStatus.value = 'connecting'

  // 获取JWT token
  const token = localStorage.getItem('access_token')
  if (!token) {
    ElMessage.error('未找到认证token，请重新登录')
    connectionStatus.value = 'failed'
    return
  }

  // 构建WebSocket URL
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
  // 使用后端服务器的地址
  const backendHost = process.env.NODE_ENV === 'development' ? 'localhost:8000' : window.location.host
  const wsUrl = `${protocol}//${backendHost}/ws/ssh/${hostInfo.value.id}/?token=${token}`

  console.log('正在连接WebSocket:', wsUrl)
  console.log('主机信息:', hostInfo.value)
  console.log('Token:', token.substring(0, 50) + '...')

  websocket = new WebSocket(wsUrl)

  websocket.onopen = () => {
    console.log('WebSocket连接已建立')
    ElMessage.success('WebSocket连接成功')
    startHeartbeat()
  }

  websocket.onmessage = (event) => {
    try {
      const data = JSON.parse(event.data)
      console.log('收到WebSocket消息:', data)
      handleWebSocketMessage(data)
    } catch (error) {
      console.error('解析WebSocket消息失败:', error)
    }
  }

  websocket.onclose = (event) => {
    console.log('WebSocket连接已关闭', event.code, event.reason)
    connectionStatus.value = 'disconnected'
    stopHeartbeat()

    if (event.code !== 1000) { // 非正常关闭
      ElMessage.error('SSH连接已断开')
    }
  }

  websocket.onerror = (error) => {
    console.error('WebSocket错误:', error)
    connectionStatus.value = 'failed'
    ElMessage.error('WebSocket连接失败: ' + error.message)
  }
}

const handleWebSocketMessage = (data) => {
  switch (data.type) {
    case 'output':
      if (terminal) {
        terminal.write(data.data)
      }
      break

    case 'status':
      if (data.status === 'connected') {
        connectionStatus.value = 'connected'
        ElMessage.success('SSH连接已建立')
      } else if (data.status === 'failed') {
        connectionStatus.value = 'failed'
        ElMessage.error(data.message || 'SSH连接失败')
      }

      if (data.message && terminal) {
        terminal.writeln(data.message)
      }
      break

    case 'pong':
      // 心跳响应
      break

    default:
      console.log('未知消息类型:', data.type)
  }
}

const startHeartbeat = () => {
  heartbeatInterval = setInterval(() => {
    if (websocket && websocket.readyState === WebSocket.OPEN) {
      websocket.send(JSON.stringify({ type: 'ping' }))
    }
  }, 30000) // 30秒心跳
}

const stopHeartbeat = () => {
  if (heartbeatInterval) {
    clearInterval(heartbeatInterval)
    heartbeatInterval = null
  }
}

const handleResize = () => {
  if (fitAddon) {
    fitAddon.fit()
  }
}

const reconnect = () => {
  if (websocket) {
    websocket.close()
  }

  setTimeout(() => {
    connectWebSocket()
  }, 1000)
}

const closeTerminal = () => {
  if (websocket) {
    websocket.close()
  }
  router.go(-1)
}

const getStatusType = (status) => {
  const map = {
    disconnected: 'info',
    connecting: 'warning',
    connected: 'success',
    failed: 'danger'
  }
  return map[status] || 'info'
}

const getStatusText = (status) => {
  const map = {
    disconnected: '未连接',
    connecting: '连接中',
    connected: '已连接',
    failed: '连接失败'
  }
  return map[status] || '未知'
}

onMounted(async () => {
  console.log('SSHTerminal组件已挂载')
  await loadHostInfo()
  await nextTick()
  console.log('正在初始化终端')
  initTerminal()
  console.log('正在连接WebSocket')
  connectWebSocket()
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  stopHeartbeat()

  if (websocket) {
    websocket.close()
  }

  if (terminal) {
    terminal.dispose()
  }
})
</script>

<style scoped>
.ssh-terminal {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: #1e1e1e;
  color: #ffffff;
  position: relative;
}

.terminal-header {
  background-color: #2d2d2d;
  padding: 10px 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #444;
  z-index: 10;
}

.header-left {
  display: flex;
  align-items: center;
}

.header-left h3 {
  margin: 0;
  color: #ffffff;
  font-size: 16px;
}

.header-right {
  display: flex;
  gap: 10px;
}

.terminal-container {
  flex: 1;
  position: relative;
  overflow: hidden;
}

.terminal-element {
  width: 100%;
  height: 100%;
  padding: 10px;
}

.connection-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 20;
}

.connection-message {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #ffffff;
  font-size: 16px;
}

/* 覆盖xterm.js的默认样式 */
:deep(.xterm) {
  height: 100% !important;
}

:deep(.xterm-viewport) {
  background-color: transparent !important;
}

:deep(.xterm-screen) {
  background-color: transparent !important;
}
</style>
